package br.com.atid.view.util
{


	import flash.display.Graphics;
	import flash.geom.Point;

	import mx.core.UIComponent;

	/**
	 *
	 * Copyright (c) 2008 Noel Billig (www.dncompute.com)
	 *
	 * Permission is hereby granted, free of charge, to any person obtaining a copy
	 * of this software and associated documentation files (the "Software"), to deal
	 * in the Software without restriction, including without limitation the rights
	 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	 * copies of the Software, and to permit persons to whom the Software is
	 * furnished to do so, subject to the following conditions:
	 *
	 * The above copyright notice and this permission notice shall be included in
	 * all copies or substantial portions of the Software.
	 *
	 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	 * THE SOFTWARE.
	 */


	public class GraphicsUtil
	{


		public static function drawArrow(graphics:Graphics, start:Point, end:Point, style:Object=null):void
		{

			if (start.equals(end))
				return;

			var arrowStyle:ArrowStyle;
			if (style == null)
			{
				arrowStyle=new ArrowStyle();
			}
			else if (style is ArrowStyle)
			{
				arrowStyle=style as ArrowStyle;
			}
			else
			{
				arrowStyle=new ArrowStyle(style);
			}

			var fullVect:Point=end.subtract(start);
			var halfWidth:Number=(arrowStyle.headWidth != -1) ? arrowStyle.headWidth / 2 : arrowStyle.headLength / 2;

			//Figure out the line start/end points
			var startNorm:Point=new Point(fullVect.y, -fullVect.x);
			startNorm.normalize(arrowStyle.shaftThickness / 2);
			var start1:Point=start.add(startNorm);
			var start2:Point=start.subtract(startNorm);
			var end1:Point=end.add(startNorm);
			var end2:Point=end.subtract(startNorm);

			//figure out where the arrow head starts
			var headPnt:Point=fullVect.clone();
			headPnt.normalize(headPnt.length - arrowStyle.headLength);
			headPnt=headPnt.add(start);

			//calculate the arrowhead corners
			var headPntNorm:Point=startNorm.clone();
			headPntNorm.normalize(halfWidth);
			var edge1:Point=headPnt.add(headPntNorm);
			var edge2:Point=headPnt.subtract(headPntNorm);

			//Figure out where the arrow connects the the shaft, then calc the intersections
			var shaftCenter:Point=Point.interpolate(end, headPnt, arrowStyle.shaftPosition);
			var inter1:Point=GeomUtil.getLineIntersection(start1, end1, shaftCenter, edge1);
			var inter2:Point=GeomUtil.getLineIntersection(start2, end2, shaftCenter, edge2);

			//Figure out the control points
			var edgeCenter:Point=Point.interpolate(end, headPnt, arrowStyle.edgeControlPosition);
			var edgeNorm:Point=startNorm.clone();
			edgeNorm.normalize(halfWidth * arrowStyle.edgeControlSize);
			var edgeCntrl1:Point=edgeCenter.add(edgeNorm);
			var edgeCntrl2:Point=edgeCenter.subtract(edgeNorm);


			graphics.moveTo(start1.x, start1.y);
			graphics.lineTo(inter1.x, inter1.y);
			graphics.lineTo(edge1.x, edge1.y);
			graphics.curveTo(edgeCntrl1.x, edgeCntrl1.y, end.x, end.y);
			graphics.curveTo(edgeCntrl2.x, edgeCntrl2.y, edge2.x, edge2.y);
			graphics.lineTo(inter2.x, inter2.y);
			graphics.lineTo(start2.x, start2.y);
			graphics.lineTo(start1.x, start1.y);
		}


		/**
		 *
		 * @param graphics
		 * @param start
		 * @param end
		 * @param style
		 *
		 */
		public static function drawArrowHead(graphics:Graphics, start:Point, end:Point, style:Object=null):void
		{

			var arrowStyle:ArrowStyle;
			if (style == null)
			{
				arrowStyle=new ArrowStyle();
			}
			else if (style is ArrowStyle)
			{
				arrowStyle=style as ArrowStyle;
			}
			else
			{
				arrowStyle=new ArrowStyle(style);
			}

			var vec:Point=end.subtract(start);
			var halfWidth:Number=(arrowStyle.headWidth != -1) ? arrowStyle.headWidth / 2 : vec.length / 2;

			var shaft:Point=vec.clone();
			shaft.normalize(vec.length * arrowStyle.shaftPosition);
			shaft=start.add(shaft);

			//Make the vect a normal to the line
			vec=new Point(vec.y, -vec.x);

			var tmp:Point=vec.clone();
			tmp.normalize(arrowStyle.shaftControlSize * halfWidth);
			var shaftCenter:Point=Point.interpolate(start, shaft, arrowStyle.shaftControlPosition);
			var baseCntrl1:Point=shaftCenter.add(tmp);
			var baseCntrl2:Point=shaftCenter.subtract(tmp);

			vec.normalize(halfWidth);
			var base1:Point=start.add(vec);
			var base2:Point=start.subtract(vec);

			var edgeCenter:Point=Point.interpolate(start, end, arrowStyle.edgeControlPosition);
			vec.normalize(halfWidth * arrowStyle.edgeControlSize);
			var edgeCntrl1:Point=edgeCenter.add(vec);
			var edgeCntrl2:Point=edgeCenter.subtract(vec);


			//Draw the arrow
			graphics.moveTo(base1.x, base1.y);
			graphics.curveTo(baseCntrl1.x, baseCntrl1.y, shaft.x, shaft.y);
			graphics.curveTo(baseCntrl2.x, baseCntrl2.y, base2.x, base2.y);
			graphics.curveTo(edgeCntrl2.x, edgeCntrl2.y, end.x, end.y);
			graphics.curveTo(edgeCntrl1.x, edgeCntrl1.y, base1.x, base1.y);

		}
	}

}
